/**
 * 
 */
package name.shamansir.tadah.data;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import android.text.format.Time;

import name.shamansir.tadah.data.Tag.Type;
import name.shamansir.tadah.data.scheduling.HasDuration;
import name.shamansir.tadah.data.scheduling.Run;
import name.shamansir.tadah.data.scheduling.Scheduling;
import name.shamansir.tadah.data.scheduling.SchedulingRule;
import name.shamansir.tadah.util.Context;

/**
 * <dl>
 * <dt>Project:</dt> <dd>ta-dah</dd>
 * <dt>Package:</dt> <dd>name.shamansir.tadah.data</dd>
 * </dl>
 *
 * <code>TodoItem</code>
 *
 * <p>Description</p>
 *
 * @author Ulric Wilfred <shaman.sir@gmail.com>
 * @date Feb 21, 2011 9:21:40 PM 
 *
 */
public class TodoItem extends WithId implements HasDuration {
    
    //public static enum State { STARTED, IN_PROGRESS, FINISHED };
    
    private String title;
    private String body;
    private final Scheduling scheduling;
        
    private final Set<Tag> tags = new LinkedHashSet<Tag>();    
    private final List<TodoItem> children = new LinkedList<TodoItem>();
    private final List<Attachment> attachments = new ArrayList<Attachment>();
    
    private Run progress = null;
    private int priority = -1;
    
    protected TodoItem() {
        super(-1);
        this.scheduling = Scheduling.noRules();
    }
    
    public TodoItem(int id, String title, String bodyInMarkdown, Scheduling scheduling) {
        super(id);
        this.title = title;
        this.body = bodyInMarkdown;
        this.scheduling = scheduling;        
    }
    
    public TodoItem(int id, String title, Scheduling scheduling) {
        this(id, title, "", scheduling);
    }
    
    public TodoItem(int id, String title, String bodyInMarkdown) {
        this(id, title, bodyInMarkdown, Scheduling.noRules());
    }
    
    public TodoItem(int id, String title) {
        this(id, title, "", Scheduling.noRules());
    }
    
    public String getTitle() { return this.title; };
    
    public String getBody() { return this.body; };    
    
    public Scheduling getScheduling() { return this.scheduling; };
    
    public Run getProgress() { return this.progress; };
    
    public boolean hasProgress() { return (this.progress != null); };    
    
    public boolean isDone() { return (this.progress == null) ||
                                      this.progress.noEnd(); };
    
    public boolean hasChildren() { return children.isEmpty(); }
    
    /* public boolean matchesProject(Project project) { return projects.contains(project); }
    
    public boolean matchesLocation(Location location) { return locations.contains(location); } */
    
    public boolean hasTag(Tag tag) { return tags.contains(tag); }
    
    public boolean hasTag(String name) { return hasTag(null, name); }    
    
    public boolean hasTag(Type type, String name) {
        // FIXME: group tags by type?
        for (Tag tag: tags) {
            if (tag.getName().equals(name) &&
               (((type == null) && tag.getType().equals(Type.NORMAL)) ||
                (tag.getType().equals(type)))) return true;
        }
        return false;
    }
    
    public int getPriority() { return priority; } 
    
    public List<TodoItem> getChildren() { return children; }
    
    public Set<Tag> getTags() { return tags; }    
    
    public List<Attachment> getAttachments() { return attachments; }
    
    public void changeTitle(String title) { this.title = (title != null) ? title : ""; }
    
    public void changeBody(String bodyHtml) { this.body = (bodyHtml != null) ? bodyHtml : ""; }
    
    public void changePriority(int priority) { this.priority = priority; }
    
    //public void updateScheduling(Scheduling scheduling) { this.scheduling = (scheduling != null) ? scheduling : Scheduling.noRules(); }
    
    public void setProgress(Run progress) { this.progress = progress; }
        
    public void addChild(TodoItem item) { children.add(item);  }
    
    public void addChildren(List<TodoItem> items) { children.addAll(items); };
    
    public void addAttachment(Attachment attachment) { attachments.add(attachment); }
    
    public void addTag(Tag tag) { tags.add(tag); }
    
    public void addTag(String name) { addTag(null, name); }    
    
    public void addTag(Type type, String name) { tags.add(new Tag(type, name)); }    
    
    public void addTags(Set<Tag> tags) { this.tags.addAll(tags); }
        
    public void addRule(SchedulingRule rule) { this.scheduling.addRule(rule); }
    
    public void addRules(Set<SchedulingRule> rules) { this.scheduling.addRules(rules); }
    
    public void removeChild(TodoItem child) { children.remove(child); }
    
    public void removeAttachment(Attachment attachment) { attachments.remove(attachment); }
    
    public void removeTag(Tag tag) { tags.remove(tag); }    
    
    public void insertChild(int position, TodoItem child) { children.add(position, child); }
    
    public void replaceChild(int position, TodoItem child) { children.remove(position);
                                                             children.add(position, child); }
    
    public void validateScheduling() { scheduling.removeOverlaps(); }
    
    public void changeChildPosition(int newPos, TodoItem child) { 
        children.remove(child);
        children.add(newPos, child);
    }
    
    @Override
    public Run match(Time start, Time end) { return scheduling.match(start, end); }
    
    public static TodoItem parse(String source) {
        return Context.parser.parse(source);
    }
    
    public String geekCode() {
        return geekCode(this);
    }
    
    public static String geekCode(TodoItem item) {
        return Context.gParser.encode(item);
    }

}
